package com.cnc.bas.util;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException;

import javax.net.SocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;

import org.apache.commons.httpclient.ConnectTimeoutException;
import org.apache.commons.httpclient.HttpClientError;
import org.apache.commons.httpclient.params.HttpConnectionParams;
import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;

import com.cnc.fd.util.EasyX509TrustManager;


public class EasySSLProtocolSocketFactory implements SecureProtocolSocketFactory {
	 

    /** Log object for this class. */
	 
//	private static final Log log= LogFactory.getLog(EasySSLProtocolSocketFactory.class);
	 
	
	 private SSLContext sslcontext = null;
	 
	
	     /**
	 
	     * Constructor for EasySSLProtocolSocketFactory.
	 
	    */
	 
	 public EasySSLProtocolSocketFactory() {
	 
	        super();
	 
	}
	 

	private static SSLContext createEasySSLContext() {
	 
	try {
	 
	            SSLContext context = SSLContext.getInstance("SSL");
	 
	          context.init(
	 
	              null, 
	 
	              new TrustManager[] {(TrustManager)new EasyX509TrustManager(null)}, 
	 
	               null);
	 
	            return context;
	 
	       } catch (Exception e) {
	 
//	           LOG.error(e.getMessage(), e);
	 
	          throw new HttpClientError(e.toString());
	 
	        }
	 
	   }
	 
	  
	     private SSLContext getSSLContext() {
	 
	         if (this.sslcontext == null) {
	 
	            this.sslcontext = createEasySSLContext();
	 
	         }
	 
	        return this.sslcontext;
	 
	     }
	 
	 
	    /**
	 
	     * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int,java.net.InetAddress,int)
	 
	      */
	 
	     public Socket createSocket(
	 
	        String host,
	 
	         int port,
	 
	         InetAddress clientHost,
	 
	         int clientPort)
	 
	        throws IOException, UnknownHostException {
	 
	  
	         return getSSLContext().getSocketFactory().createSocket(
	 
	            host,
	 
	            port,
	 
            clientHost,
	 
	            clientPort
	 
        );
	 
     }
	 
 
	     /**
	 
     * Attempts to get a new socket connection to the given host within the given time limit.
	 
	153      * <p>
	 
	154      * To circumvent the limitations of older JREs that do not support connect timeout a 
	 
	155      * controller thread is executed. The controller thread attempts to create a new socket 
	 
	156      * within the given limit of time. If socket constructor does not return until the 
	 
	157      * timeout expires, the controller terminates and throws an {@link ConnectTimeoutException}
	 
	158      * </p>
	 
	159      *  
	 
	160      * @param host the host name/IP
	 
	161      * @param port the port on the host
	 
	162      * @param clientHost the local host name/IP to bind the socket to
	 
	163      * @param clientPort the port on the local machine
	 
	164      * @param params {@link HttpConnectionParams Http connection parameters}
	 
	165      * 
	 
	166      * @return Socket a new socket
	 
	167      * 
	 
	168      * @throws IOException if an I/O error occurs while creating the socket
	 
	169      * @throws UnknownHostException if the IP address of the host cannot be
	 
	170      * determined
	 
	171      */
	 
	   public Socket createSocket(
	 
	        final String host,
	 
	        final int port,
	 
	        final InetAddress localAddress,
	 
         final int localPort,
	 
	         final HttpConnectionParams params
	 
	     ) throws IOException, UnknownHostException, ConnectTimeoutException {
	 
	         if (params == null) {
	 
	            throw new IllegalArgumentException("Parameters may not be null");
	 
	         }
	 
	        int timeout = params.getConnectionTimeout();
	 
	        SocketFactory socketfactory = getSSLContext().getSocketFactory();
	 
	        if (timeout == 0) {
	 
	           return socketfactory.createSocket(host, port, localAddress, localPort);
	 
	        } else {
	 
	            Socket socket = socketfactory.createSocket();
	 
	            SocketAddress localaddr = new InetSocketAddress(localAddress, localPort);
	 
	             SocketAddress remoteaddr = new InetSocketAddress(host, port);
	 
	            socket.bind(localaddr);
	 
	             socket.connect(remoteaddr, timeout);
	 
	             return socket;
	 
	        }
	 
    }
	 
	 
	    /**
	 
	      * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int)
	 
	198      */
	 
	     public Socket createSocket(String host, int port)
	 
	        throws IOException, UnknownHostException {
	 
	        return getSSLContext().getSocketFactory().createSocket(
	 
	            host,
	 
	            port
	 
	         );
	 
	    }
	 
	 
	     /**
	 
	      * @see SecureProtocolSocketFactory#createSocket(java.net.Socket,java.lang.String,int,boolean)
	 
	      */
	 
	     public Socket createSocket(
	 
	         Socket socket,
	 
	        String host,
	 
	         int port,
	 
	         boolean autoClose)
	 
	        throws IOException, UnknownHostException {
	 
	         return getSSLContext().getSocketFactory().createSocket(
	 
	            socket,
	            host,
	           port,
	           autoClose
	 
	         );
	 
	    }
	 
 
	    public boolean equals(Object obj) {
	 
	         return ((obj != null) && obj.getClass().equals(EasySSLProtocolSocketFactory.class));
	 
	     }
	 
	  
	     public int hashCode() {
	 
	        return EasySSLProtocolSocketFactory.class.hashCode();
	 
	    }
	 
	  
	 }
	 
